/*
 * Copyright 2020 eBlocker Open Source UG (haftungsbeschraenkt)
 *
 * Licensed under the EUPL, Version 1.2 or - as soon they will be
 * approved by the European Commission - subsequent versions of the EUPL
 * (the "License"); You may not use this work except in compliance with
 * the License. You may obtain a copy of the License at:
 *
 *   https://joinup.ec.europa.eu/page/eupl-text-11-12
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
package org.eblocker.lists.malware;

import org.eblocker.server.common.malware.MalwareUtils;
import org.eblocker.lists.util.HttpClient;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.zip.GZIPInputStream;

public class PhishtankDownloader {

    private static final Logger log = LoggerFactory.getLogger(PhishtankDownloader.class);

    private static final String URL_KEY = "provider.phishtank.url";
    private static final String PREFIX_KEY = "provider.phishtank.filteredUrls.prefix";

    private final HttpClient httpClient;
    private final ObjectMapper objectMapper;
    private final String url;
    private final String prefix;

    public PhishtankDownloader(Properties properties, ObjectMapper objectMapper, HttpClient httpClient) {
        this.httpClient = httpClient;
        this.objectMapper = objectMapper;
        url = properties.getProperty(URL_KEY);
        prefix = properties.getProperty(PREFIX_KEY);
    }

    public List<PhishtankEntry> retrieveEntries() throws IOException, MalwareListException {
        return parseEntries(downloadData());
    }

    private JsonNode downloadData() throws IOException {
        log.debug("downloading phishtank data from {}", url);
        try (InputStream is = new GZIPInputStream(httpClient.download(url, "", ""))) {
            return objectMapper.readTree(is);
        }
    }

    private List<PhishtankEntry> parseEntries(JsonNode rootNode) throws MalwareListException {
        int n = 0;
        List<PhishtankEntry> entries = new ArrayList<>();
        Iterator<JsonNode> i = rootNode.iterator();
        while(i.hasNext()) {
            JsonNode node  = i.next();
            String url = MalwareUtils.normalize(getText("url", node));
            String target = getText("target", node);
            entries.add(new PhishtankEntry(url, prefix + target));
            ++n;
        }
        log.debug("parsed {} phishtank entries", n);
        return entries;
    }

    private String getText(String key, JsonNode node) throws MalwareListException {
        JsonNode textNode = node.get(key);
        if (textNode == null) {
            throw new MalwareListException("missing json attribute: " + key);
        }
        return textNode.asText();
    }
}
